package com.example.k12.dialog

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.os.Handler
import android.os.Looper
import android.os.RemoteException
import android.text.TextUtils
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.LogUtils
import com.example.k12.R
import com.example.k12.activity.MainViewModel
import com.example.k12.base.BaseDialog
import com.example.k12.bean.PayRes
import com.example.k12.databinding.DialogWxFacePayBinding
import com.example.k12.utlis.WxPayUtils
import com.tencent.wxpayface.IWxPayfaceCallback
import com.tencent.wxpayface.WxPayFace
import com.tencent.wxpayface.constants.FacePayConstants
import com.tencent.wxpayface.constants.FacePayConstants.KEY_RET_VERIFY_USERINFO_LIST
import com.tencent.wxpayface.data.UserInfo
import java.io.UnsupportedEncodingException
import kotlin.concurrent.Volatile
import androidx.core.graphics.toColorInt

@Suppress("FORBIDDEN_IDENTITY_EQUALS_WARNING")
class WxFacePayDialog(private val context: Context) :
    BaseDialog<DialogWxFacePayBinding>(context) {

    // 通过Activity获取ViewModel实例
    private val mainViewModel: MainViewModel by lazy {
        ViewModelProvider(context as FragmentActivity)[MainViewModel::class.java]
    }

    private var phone: String = ""
    private var mPhoneInput: EditText? = null
    val TAG = "WxFacePayDialog"

    @Volatile
    private var retryCount = 5 //请求重试次数
    private var isPreviewSet = false
    private var userInfo: UserInfo? = null //识别到的用户信息
    private var mLastUserInfos: List<UserInfo>? = null
    private val mainHandler = Handler(Looper.getMainLooper())
    private var faceVerifyId: String? = null //识别链路id
    private var payToken: String? = null //支付凭证

    @Volatile
    private var setCameraRetryCount = 5 //请求绑定预览重试次数
    override fun getWidth(): Int {
        return context.resources.getDimensionPixelSize(R.dimen.dp400) // 屏幕宽度的一半
    }

    @SuppressLint("SetTextI18n")
    override fun initData() {
        // 初始化数据
        setWxCameraPreview()
        mBinding.btnPay.setOnClickListener {
            safeClick {
                mainViewModel.toPay(payToken!!) {
                    PayResultDialog(context, it).show()
                    dismiss()
                }
            }
        }
    }

    private fun setWxCameraPreview() {
        LogUtils.d("TAG", "setCamera")
        //注意surface一定有值，可以用surfaceview.addCallback来确定surface已经成功创建
        WxPayFace.getInstance()
            .setCameraPreview(
                mBinding.circleImage,
                WxPayUtils.params,
                object : IWxPayfaceCallback() {
                    @Throws(RemoteException::class)
                    override fun response(info: Map<*, *>?) {
                        if (!isSuccessInfo("setCameraPreview", info)) {
                            setCameraRetryCount--
                            if (setCameraRetryCount > 0) {
                                setWxCameraPreview()
                            }
                            return
                        }
                        val outputMsg = "setCameraPreview成功"
                        upDataHint(outputMsg)
                        isPreviewSet = true
                    }
                },
                false
            )

        startVerify()
    }

    /**
     * 请求是否成功
     *
     * @param apiName 命令名
     * @param info    请求信息
     * @return
     */
    private fun isSuccessInfo(apiName: String, info: Map<*, *>?): Boolean {
        if (info == null) {
            upDataHint("调用返回为空, 请查看日志")
            RuntimeException("调用返回为空").printStackTrace()
            return false
        }
        val code = info[FacePayConstants.KEY_RET_PARAMS_CODE] as String?
        val msg = info[FacePayConstants.KEY_RET_PARAMS_MSG] as String?
        var bsErrorCode: Int? = null
        if (info.containsKey(FacePayConstants.KEY_RET_COMMON_ERROR_CODE)) {
            bsErrorCode = info[FacePayConstants.KEY_RET_COMMON_ERROR_CODE] as Int?
        }
        LogUtils.i(
            TAG,
            "isSuccessInfo code:$code,bsErrorCode:$bsErrorCode,msg:$msg"
        )
        if (TextUtils.equals(code, FacePayConstants.VAL_RST_PARAMS_SUCCESS)) {
            LogUtils.i(TAG, "调用返回成功")
            return true
        }
        val outputTxt = apiName + "结果:" + code + "," + bsErrorCode + "," + msg
        LogUtils.i(TAG, outputTxt)
        upDataHint(msg ?: "")
        //注意类型要判空，不能用int
        val errorCode = info[WxPayFace.KEY_RET_COMMON_ERROR_CODE] as Int?
        if ((errorCode === WxPayFace.ERR_FACE_APP_CONNECT_SERVICE_NOT_INIT
                    || errorCode === WxPayFace.ERR_FACE_APP_CONNECT_SERVICE_INITING)
        ) {
            retryCount--
            if (retryCount <= 0) {
                WxPayFace.getInstance().releaseWxpayface(context)
            }
            val currentHandler = Handler()
            currentHandler.postDelayed({
                WxPayFace.getInstance()
                    .initWxpayface(context, object : IWxPayfaceCallback() {
                        @Throws(RemoteException::class)
                        override fun response(info: Map<*, *>?) {
                            if (!isSuccessInfo("init", info)) {
                                return
                            }
                        }
                    })
            }, 500)
        }
        return false
    }

    /**
     * 开始识别
     */
    private fun startVerify() {
        LogUtils.d("TAG", "startVerify")
        //        reportAction(FacePayConstants.MCH_ACTION_CLICK_FACE_SCAN);
        val params: HashMap<*, *> = WxPayUtils.params
        WxPayFace.getInstance().startVerify(params, object : IWxPayfaceCallback() {
            @Throws(RemoteException::class)
            override fun response(info: Map<*, *>) {
                if (!isSuccessInfo("startVerify", info)) {
                    return
                }
                val code = info[FacePayConstants.KEY_RET_PARAMS_CODE] as String?
                //一定要注意错误码的判断，如果直接用int强转会导致应用crash
                var bsErrorCode: Int? = null
                if (info.containsKey(FacePayConstants.KEY_RET_COMMON_ERROR_CODE)) {
                    bsErrorCode = info[FacePayConstants.KEY_RET_COMMON_ERROR_CODE] as Int?
                }
                val errorCode = bsErrorCode
                val msg = info[FacePayConstants.KEY_RET_PARAMS_MSG] as String?
                val verifyId =
                    (info[FacePayConstants.KEY_RET_PARAMS_FACE_VERIFY_ID]) as String?
                //是否需要辅助验证
                val needExtVerify =
                    (info[FacePayConstants.KEY_RET_PARAMS_NEED_EXT_VERIFY]) as Boolean?
                LogUtils.i(
                    TAG,
                    ("startVerify response:code=" + code + ",errorCode=" + errorCode + ",msg=" + msg + ",needExtVerify="
                            + needExtVerify)
                )
                val bitmap =
                    info[FacePayConstants.KEY_RET_VERIFY_BEST_FACE_IMG] as Bitmap?

                mLastUserInfos =
                    info[KEY_RET_VERIFY_USERINFO_LIST] as? List<UserInfo>
                if (mLastUserInfos == null || mLastUserInfos?.size == 0) {
                    val outputMsg =
                        "识别成功但没有用户信息返回\n请联系食堂技术人员解决".trimIndent()
                    showEro(outputMsg)
                    return
                }
                LogUtils.i(
                    TAG,
                    "识别成功：userInfo:$mLastUserInfos,verifyId:$verifyId,needExtVerify:$needExtVerify"
                )
                upDataHint("识别成功")
                mainHandler.post {
                    if (needExtVerify != null) {
                        if (needExtVerify) {
                            InputPhoneDialog(context,bitmap){
                                finishFaceVerify(it)
                            }.show()
                        } else {
                            userInfo = mLastUserInfos?.get(0)
                            finishFaceVerify();//识别成功后完成识别
                        }
                    }
                }
            }

        })
    }

    /**
     * 完成识别
     */
    fun finishFaceVerify(inputPhone: String = "") {
        val requestParams: MutableMap<String, String> = WxPayUtils.params
        LogUtils.d("手机号", inputPhone)
        requestParams[FacePayConstants.KEY_RET_VERIFY_PHONE] = inputPhone
        WxPayFace.getInstance().finishFaceVerify(requestParams, object : IWxPayfaceCallback() {
            @Throws(RemoteException::class)
            override fun response(info: Map<*, *>) {
                if (!isSuccessInfo("finishFaceVerify", info)) {
                    showEro("查询用户失败\n请联系食堂技术人员解决")
                    return
                }
                val code = info[FacePayConstants.KEY_RET_PARAMS_CODE] as String?
                val msg = info[FacePayConstants.KEY_RET_PARAMS_MSG] as String?
                if (TextUtils.equals(code, FacePayConstants.VAL_RST_PARAMS_SUCCESS)) {
                    userInfo = info[FacePayConstants.KEY_RET_VERIFY_USERINFO] as UserInfo?
                    LogUtils.d("userInfo = ${userInfo.toString()}")
                    val verifyId =
                        (info[FacePayConstants.KEY_RET_PARAMS_FACE_VERIFY_ID]) as String?
                    if (userInfo != null && !TextUtils.isEmpty(userInfo!!.userId)) {
                        ("完成识别成功:" + userInfo!!.userId +"，可以获取凭证:"
                                + verifyId)
                        getUserInfo()
                        upDataHint("识别成功")
                    } else {
                        showEro("识别成功但是没有用户返回\n请联系食堂技术人员解决")
                    }


                }

            }

        })
    }

    @SuppressLint("SetTextI18n")
    private fun getUserInfo() {
        mainViewModel.getUserInfo(userInfo?.outUserId ?: "") { studenRes, msg ->
            if (studenRes == null){
                dismiss()
                PayResultDialog(context, PayRes(msg = msg, code = 1)).show()
            }else{
                mBinding.tvWait.visibility = View.GONE
                mBinding.circleImage.setOverlayColor("#1aad19".toColorInt())
                mBinding.viewFinishVerify.visibility = View.VISIBLE
                mBinding.tvUserName.visibility = View.VISIBLE
                mBinding.llPaying.visibility = View.VISIBLE
                mBinding.tvAmount2.text = "请支付 ¥ ${mainViewModel.totalAmount}"
                mBinding.tvUserName.text = studenRes.name
//            performUserInfoAnimation()
                getFacePayCredential()
            }
        }
    }

    /**
     * 执行用户信息获取后的动画效果
     * 包括circleImage缩小和llPaying渐显动画
     */
    private fun performUserInfoAnimation() {
        mBinding.circleImage.animate()
            .scaleX(0.8f)
            .scaleY(0.8f)
            .setDuration(300)
            .withEndAction {
                // 重新设置SurfaceView的显示状态
                mBinding.circleImage.visibility = View.GONE
                mBinding.circleImage.visibility = View.VISIBLE
            }
            .start()

        // 显示支付信息
        mBinding.llPaying.alpha = 0f
        mBinding.llPaying.visibility = View.VISIBLE
        mBinding.llPaying.animate()
            .alpha(1f)
            .setDuration(300)
            .start()
    }


    /**
     * 将ImageView转换为圆形显示并添加边框
     */
    private fun makeImageViewCircularWithBorder(imageView: ImageView) {
        imageView.clipToOutline = true
        imageView.outlineProvider = object : android.view.ViewOutlineProvider() {
            override fun getOutline(view: android.view.View, outline: android.graphics.Outline) {
                outline.setOval(0, 0, view.width, view.height)
            }
        }
    }

    /**
     * 获取支付凭证
     */
    fun getFacePayCredential() {
        val requestParams: MutableMap<String, String> = WxPayUtils.params
        if (userInfo != null) {
            requestParams[FacePayConstants.KEY_RET_VERIFY_USERID] = userInfo!!.userId
        }
        requestParams[FacePayConstants.KEY_REQ_PARAMS_TOTAL_FEE] = (mainViewModel.totalAmount * 100).toInt().toString()
        WxPayFace.getInstance().getFacePayCredential(requestParams, object : IWxPayfaceCallback() {
            @Throws(RemoteException::class)
            override fun response(info: Map<*, *>) {
                val msg = info[FacePayConstants.KEY_RET_PARAMS_MSG] as String?
                if (!isSuccessInfo("getFacePayCredential", info)) {
                    mainHandler.post {
                        if (TextUtils.isEmpty(msg)) {
                            showEro("获取支付凭证失败\n请联系食堂技术人员解决")
                        } else {
                            showEro("获取支付凭证失败:$msg")
                        }
                    }
                    return
                }
                //                reportAction(FacePayConstants.MCH_ACTION_GET_PAY_CRED_SUCCESS);
                val code = info[FacePayConstants.KEY_RET_PARAMS_CODE] as String?

                var outputMsg = "获取凭证失败:$code,$msg"
                if (TextUtils.equals(code, FacePayConstants.VAL_RST_PARAMS_SUCCESS)) {
                    payToken =
                        (info[FacePayConstants.KEY_RET_PARAMS_FACE_TOKEN]) as String?
                    if (payToken != null) {
                        faceVerifyId =
                            (info[FacePayConstants.KEY_RET_PARAMS_FACE_VERIFY_ID]) as String?
                        if (!TextUtils.isEmpty(payToken)) {
                            outputMsg =
                                ("获取凭证成功:可以启动扣款verifyId:${faceVerifyId}".trimIndent())
                            if (payToken!!.length > 4000) {
                                var i = 0
                                while (i < payToken!!.length) {
                                    if (i + 4000 < payToken!!.length) LogUtils.e(
                                        TAG,
                                        "payToken第一段log===" + payToken!!.substring(i, i + 4000)
                                    )
                                    else {
                                        LogUtils.e(
                                            TAG,
                                            "payToken第二段log===" + payToken!!.substring(
                                                i,
                                                payToken!!.length
                                            )
                                        )
                                    }
                                    i += 4000
                                }
                            } else {
                                LogUtils.e(TAG, "充值记录查询response===$payToken")
                            }
                            try {
                                LogUtils.i(
                                    TAG,
                                    "length:" + payToken!!.toByteArray(charset("utf-8")).size
                                )
                            } catch (e: UnsupportedEncodingException) {
                                LogUtils.e(TAG, "getfacetoken error:", e)
                            }
                        } else {
                            outputMsg = "获取凭证成功 MSG:$msg"
                        }
                    }
                }
                upDataHint(outputMsg)
            }
        })
    }


    /**
     * 展示toast
     *
     * @param text
     */
    private fun upDataHint(text: String) {
        mainHandler.post { mBinding.tvWait.text = text }
    }

    /**
     * 支付失败
     * @param outputMsg 显示错误信息
     */
    private fun showEro(outputMsg: String) {
        mainHandler.post {
            PayResultDialog(context, PayRes(outputMsg, 1)).show()
            dismiss()
        }
    }

}